package vn.edu.ptithcm.pim.controller;

import java.io.File;
import java.net.FileNameMap;
import java.net.URLConnection;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.validation.BindException;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.support.StringMultipartFileEditor;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.SimpleFormController;

import vn.edu.ptithcm.pim.common.bean.Attachment;
import vn.edu.ptithcm.pim.common.bean.SendMailObject;
import vn.edu.ptithcm.pim.constant.Constants;
import vn.edu.ptithcm.pim.constant.Locales;
import vn.edu.ptithcm.pim.constant.TaskStatuses;
import vn.edu.ptithcm.pim.constant.UrlConstants;
import vn.edu.ptithcm.pim.dom.ActivityLog;
import vn.edu.ptithcm.pim.dom.Employee;
import vn.edu.ptithcm.pim.dom.Project;
import vn.edu.ptithcm.pim.dom.Resource;
import vn.edu.ptithcm.pim.dom.Task;
import vn.edu.ptithcm.pim.dom.TaskCategory;
import vn.edu.ptithcm.pim.dom.TaskLog;
import vn.edu.ptithcm.pim.dom.TaskPriority;
import vn.edu.ptithcm.pim.dom.TaskSeverity;
import vn.edu.ptithcm.pim.dom.TaskStatus;
import vn.edu.ptithcm.pim.dom.User;
import vn.edu.ptithcm.pim.service.ActivityLogService;
import vn.edu.ptithcm.pim.service.EmployeeFunctionInProjectService;
import vn.edu.ptithcm.pim.service.EmployeeService;
import vn.edu.ptithcm.pim.service.PhaseService;
import vn.edu.ptithcm.pim.service.ProjectService;
import vn.edu.ptithcm.pim.service.ResourceService;
import vn.edu.ptithcm.pim.service.SendMailService;
import vn.edu.ptithcm.pim.service.TaskCategoryService;
import vn.edu.ptithcm.pim.service.TaskLogService;
import vn.edu.ptithcm.pim.service.TaskPriorityService;
import vn.edu.ptithcm.pim.service.TaskService;
import vn.edu.ptithcm.pim.service.TaskSeverityService;
import vn.edu.ptithcm.pim.service.TaskStatusService;
import vn.edu.ptithcm.pim.service.UserService;
import vn.edu.ptithcm.pim.util.DateTimeUtil;
import vn.edu.ptithcm.pim.util.DocumentUtil;
import vn.edu.ptithcm.pim.util.FileUtil;
import vn.edu.ptithcm.pim.util.ParamUtil;
import vn.edu.ptithcm.pim.util.TaskStatusUtil;

@SuppressWarnings("deprecation")
public class AddTasksController extends SimpleFormController {
	private TaskService taskService;
	private UserService userService;
	private TaskSeverityService taskSeverityService;
	private TaskCategoryService taskCategoryService;
	private TaskPriorityService taskPriorityService;
	private TaskStatusService taskStatusService;
	private ProjectService projectService;
	private EmployeeFunctionInProjectService employeeFunctionInProjectService;
	private EmployeeService employeeService;
	private TaskLogService taskLogService;
	private PhaseService phaseService;
	private SendMailService sendMailService;
	private ResourceService resourceService;
	private LocaleResolver localeResolver;
	private ActivityLogService activityLogService;

	Logger log = Logger.getLogger(AddTasksController.class);

	public AddTasksController() {
		super();
		setSessionForm(true);
		setCommandName("task");
		setCommandClass(Task.class);
		setFormView(UrlConstants.ADD_TASK_URL);
		setSuccessView(UrlConstants.ADD_TASK_URL);
	}

	@Override
	protected Object formBackingObject(HttpServletRequest request)
			throws Exception {
		return new Task();
	}

	@Override
	public void initBinder(HttpServletRequest request,
			ServletRequestDataBinder binder) throws Exception {
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
		binder.registerCustomEditor(Date.class, new CustomDateEditor(
				dateFormat, true));
		if (request instanceof MultipartHttpServletRequest) {
			binder.registerCustomEditor(String.class,
					new StringMultipartFileEditor());
		}
	}

	@Override
	protected ModelAndView onSubmit(HttpServletRequest request,
			HttpServletResponse response, Object command, BindException errors)
			throws Exception {
		String parent_tcode = ParamUtil.getString(request, "parent_tcode", "");
		Task informTask = (Task) command;
		String loginName = userService.getCurrentLogin(request);
		User user = userService.findByLoginName(loginName);
		String visa = user.getEmployee().getVisa();
		if (user != null) {
			int pnum = ParamUtil.getInteger(request, "pnum", 0);
			Project project = projectService.findByNumber(pnum);
			if (project != null) {
				String tcode = "";
				int n = taskService.getNumberOfItems(project.getProjectid());
				if (n == 0) {
					tcode = String.valueOf(project.getNumber()) + "1";
				} else {
					long maxId = taskService.getMaximumId(project
							.getProjectid());
					Task task = taskService.findById(new Long(maxId));

					tcode = String.valueOf(project.getNumber())
							+ String.valueOf(Integer.valueOf(StringUtils
									.substringAfter(task.getCode(),
											String.valueOf(project.getNumber()))) + 1);
				}

				informTask.setProject(project);
				informTask.setCode(tcode);
				informTask.setReporter(userService.getVisa(visa));
				Date now = new Date();

				informTask.setCreatedtime(now);
				informTask.setLastchanged(now);

				String attachedfiles = ParamUtil.getString(request,
						"_attachedfiles", "");
				if (!attachedfiles.isEmpty()) {
					informTask.setAttachedfiles(true);
				} else {
					informTask.setAttachedfiles(false);
				}

				if (informTask.getNote() == null) {
					informTask.setNote("");
				}

				taskService.save(informTask);

				Task task = taskService.findByCode(tcode);
				if (task != null) {
					if (!parent_tcode.isEmpty()) {
						log.info("parent_tcode : " + parent_tcode);
						Task patent_task = taskService.findByCode(parent_tcode);
						if (patent_task != null) {
							patent_task.getTasksForTaskchildid().add(task);
							taskService.saveOrUpdate(patent_task);
							log.info("update parent task done");
						}
					}
					request.setAttribute("addOK", true);

					List<Attachment> attachments = new ArrayList<Attachment>(0);

					if (!attachedfiles.isEmpty()) {
						String[] files = attachedfiles.split(";");
						if (files.length > 0) {
							String path = request.getSession()
									.getServletContext().getRealPath("");
							int index = StringUtils.indexOf(path, "pim");
							path = path.substring(0, index);

							for (int i = 0; i < files.length; ++i) {
								String[] fileInfo = files[i].split(",");
								if (fileInfo.length == 2) {
									Resource resource = new Resource();
									resource.setAuthor(visa);
									resource.setCreatedAt(now);
									resource.setOrignalName(DocumentUtil
											.getFileName(fileInfo[0]));
									resource.setPath(fileInfo[1]);
									resource.setSubjectId(task.getTaskid());
									resource.setSubjectType("Task");
									resource.setType(DocumentUtil
											.getFileExtension(fileInfo[0]));
									resource.setSize(FileUtil
											.getSizeInKByte(path + fileInfo[1]));

									FileNameMap fileNameMap = URLConnection
											.getFileNameMap();

									File file = FileUtils.getFile(path
											+ fileInfo[1]);

									String mimeType = fileNameMap
											.getContentTypeFor(file.getName());

									Attachment attachment = new Attachment(
											FileUtils.readFileToByteArray(file),
											DocumentUtil
													.getFileName(fileInfo[0]),
											mimeType, true);

									attachments.add(attachment);

									resourceService.save(resource);
								}
							}
						}
					}

					TaskLog taskLog = new TaskLog();
					taskLog.setTask(task);

					taskLog.setTime(now);

					taskLog.setField("Created");
					taskLog.setChange("Created");
					taskLog.setVisa(visa);
					taskLogService.save(taskLog);

					TaskCategory category = taskCategoryService.findById(task
							.getTaskCategory().getCategoryid());
					TaskSeverity severity = taskSeverityService.findById(task
							.getTaskSeverity().getSeverityid());
					TaskStatus status = taskStatusService.findById(task
							.getTaskStatus().getStatusid());
					TaskPriority priority = taskPriorityService.findById(task
							.getTaskPriority().getPriorityid());

					SendMailObject sendMailObject = new SendMailObject();

					StringBuilder subject = new StringBuilder();
					subject.append("[").append(project.getName()).append(" - ")
							.append(category.getName()).append(" #")
							.append(task.getCode()).append("]").append(" (")
							.append(status.getName()).append(") ")
							.append(task.getSummary());

					sendMailObject.setSuject(subject.toString());
					sendMailObject.setFrom(Constants.MAIL_HOST_SERVER);

					Map<String, Object> data = new HashMap<String, Object>();
					data.put("project", project);
					data.put("category", category.getName());
					data.put("severity", severity.getName());
					data.put("priority", priority.getName());
					data.put("status", status.getName());
					data.put("task", task);
					data.put("starttime", DateTimeUtil.dateToString(
							task.getStarttime(), "yyyy-MM-dd"));
					data.put("endtime", DateTimeUtil.dateToString(
							task.getEndtime(), "yyyy-MM-dd"));

					String taskDetailUrl = request
							.getRequestURL()
							.toString()
							.replaceAll(request.getServletPath(),
									"/taskDetail.htm")
							+ "?pnum=" + pnum + "&tcode=" + tcode;

					data.put("taskDetailUrl", taskDetailUrl.toString());
					data.put("visa", visa);

					sendMailObject.setData(data);

					Locale locale = getLocaleResolver().resolveLocale(request);
					if (Locales.VI.equals(locale.toString())) {
						sendMailObject.setTemplate("vi_templates/addTask.vm");
					} else if (Locales.EN.equals(locale.toString())) {
						sendMailObject.setTemplate("en_templates/addTask.vm");
					}

					Employee reporter = employeeService.findByVisa(visa);
					List<String> bcc = new ArrayList<String>();

					if (!task.getAssignedto().isEmpty()) {
						Employee assignedTo = employeeService.findByVisa(task
								.getAssignedto());
						sendMailObject.setTo(assignedTo.getEmail());
						bcc.add(reporter.getEmail());
					} else {
						sendMailObject.setTo(reporter.getEmail());
					}

					if (!task.getMonitoredby().isEmpty()) {
						Employee monitoredBy = employeeService.findByVisa(task
								.getMonitoredby());
						bcc.add(monitoredBy.getEmail());
					}

					log.info("bcc:" + bcc);

					sendMailObject.setBcc(bcc);
					sendMailObject.setAttachedFiles(attachments);

					ActivityLog activityLog = new ActivityLog();
					activityLog.setProjectId(project.getProjectid());
					activityLog.setSubjectId(task.getCode());
					activityLog.setSubjectType("Task");

					activityLog.setCreatedAt(now);

					activityLog.setCreatedBy(visa);
					activityLog.setSubjectName(subject.toString());
					activityLog.setMessage("Create");
					activityLogService.save(activityLog);

					sendMailService.send(sendMailObject);
					log.info("AddTasksController || send mail done!");
				}
			}
		}
		return showForm(request, response, errors);
	}

	@Override
	protected ModelAndView showForm(HttpServletRequest request,
			HttpServletResponse response, BindException errors)
			throws Exception {
		String parent_tcode = ParamUtil.getString(request, "parent_tcode", "");
		if (userService.isSignedIn(request)) {
			Map<String, Object> bean = new HashMap<String, Object>();
			if (parent_tcode.isEmpty()) {
				bean.put("isChildTask", false);
			} else {
				bean.put("isChildTask", true);
			}
			bean.put("parent_tcode", parent_tcode);
			String loginName = userService.getCurrentLogin(request);
			bean.put("user", userService.findByLoginName(loginName));
			bean.put("isSigned", true);
			bean.put("isAdmin", userService.isAdmin(loginName));
			bean.put(Constants.LOGIN_NAME, loginName);
			bean.put(Constants.USER_NAME, userService.getUsername(loginName));
			String visa = userService.getVisa(loginName);
			bean.put("visa", visa);
			bean.put("tab", Constants.ADD_TASKS);

			int pnum = ParamUtil.getInteger(request, "pnum", 0);
			Project project = projectService.findByNumber(pnum);
			bean.put("project", project);

			bean.put("severities", taskSeverityService.getAll());
			bean.put(
					"statuses",
					taskStatusService.findByIdList(TaskStatusUtil
							.getDependencyStatusesForShowing((int) TaskStatuses.ASSIGNED)));
			bean.put("categories", taskCategoryService.getAll());
			bean.put("priorities", taskPriorityService.getAll());
			bean.put("phases", phaseService.getAll());

			if (project != null) {
				bean.put("efips", employeeFunctionInProjectService
						.findByProjectId(project.getProjectid()));
			}

			String returnToFullPageURL = ParamUtil.getString(request,
					Constants.RETURN_TO_FULL_PAGE_URL, "");
			if (returnToFullPageURL.isEmpty()) {
				returnToFullPageURL = request.getHeader("referer");
			}
			bean.put(Constants.RETURN_TO_FULL_PAGE_URL, returnToFullPageURL);
			request.setAttribute("bean", bean);
		} else {
			int pnum = ParamUtil.getInteger(request, "pnum", 0);
			String params = "";
			if (parent_tcode.isEmpty()) {
				params = "?pnum=" + pnum;
			} else {
				params = "?pnum=" + pnum + "&parent_tcode=" + parent_tcode;
			}
			String redirectLink = UrlConstants.ADD_TASK_URL + UrlConstants.HTM
					+ params;
			log.info("AddTasksController || redirectLink : " + redirectLink);
			request.getSession().setAttribute("redirectLink", redirectLink);
			response.sendRedirect(UrlConstants.HOME_PAGE_URL + UrlConstants.HTM);
		}

		return super.showForm(request, response, errors);
	}

	public TaskSeverityService getTaskSeverityService() {
		return taskSeverityService;
	}

	public void setTaskSeverityService(TaskSeverityService taskSeverityService) {
		this.taskSeverityService = taskSeverityService;
	}

	public TaskCategoryService getTaskCategoryService() {
		return taskCategoryService;
	}

	public ProjectService getProjectService() {
		return projectService;
	}

	public void setProjectService(ProjectService projectService) {
		this.projectService = projectService;
	}

	public TaskStatusService getTaskStatusService() {
		return taskStatusService;
	}

	public void setTaskStatusService(TaskStatusService taskStatusService) {
		this.taskStatusService = taskStatusService;
	}

	public void setTaskCategoryService(TaskCategoryService taskCategoryService) {
		this.taskCategoryService = taskCategoryService;
	}

	public TaskPriorityService getTaskPriorityService() {
		return taskPriorityService;
	}

	public void setTaskPriorityService(TaskPriorityService taskPriorityService) {
		this.taskPriorityService = taskPriorityService;
	}

	public TaskService getTaskService() {
		return taskService;
	}

	public void setTaskService(TaskService taskService) {
		this.taskService = taskService;
	}

	public UserService getUserService() {
		return userService;
	}

	public void setUserService(UserService userService) {
		this.userService = userService;
	}

	public EmployeeFunctionInProjectService getEmployeeFunctionInProjectService() {
		return employeeFunctionInProjectService;
	}

	public void setEmployeeFunctionInProjectService(
			EmployeeFunctionInProjectService employeeFunctionInProjectService) {
		this.employeeFunctionInProjectService = employeeFunctionInProjectService;
	}

	public EmployeeService getEmployeeService() {
		return employeeService;
	}

	public void setEmployeeService(EmployeeService employeeService) {
		this.employeeService = employeeService;
	}

	public TaskLogService getTaskLogService() {
		return taskLogService;
	}

	public void setTaskLogService(TaskLogService taskLogService) {
		this.taskLogService = taskLogService;
	}

	public PhaseService getPhaseService() {
		return phaseService;
	}

	public void setPhaseService(PhaseService phaseService) {
		this.phaseService = phaseService;
	}

	public SendMailService getSendMailService() {
		return sendMailService;
	}

	public void setSendMailService(SendMailService sendMailService) {
		this.sendMailService = sendMailService;
	}

	public LocaleResolver getLocaleResolver() {
		return localeResolver;
	}

	public void setLocaleResolver(LocaleResolver localeResolver) {
		this.localeResolver = localeResolver;
	}

	public ResourceService getResourceService() {
		return resourceService;
	}

	public void setResourceService(ResourceService resourceService) {
		this.resourceService = resourceService;
	}

	public ActivityLogService getActivityLogService() {
		return activityLogService;
	}

	public void setActivityLogService(ActivityLogService activityLogService) {
		this.activityLogService = activityLogService;
	}

}
